home *** CD-ROM | disk | FTP | other *** search
Wrap
/*************************************************************************** * * * Filename : TeXFormat.c * * * * Description : A front-end for the PasTeX TeX implementation. * * The program looks for the format files found in the path * * TeX:Formats and enables the user to switch between the * * available format files via a gadtools interface. * * * * Return Codes : 0 - Ordinary program halt. * * 10 - No format files available. * * 20 - Couldn't open MUI application. * * 30 - No mui.library. * * * *************************************************************************** * * * Modification History * * * * Date Author Comments * * ---------------------------------------------------------------------- * * 9.3.92 R.Bödi Created. * * 8.6.92 R.Bödi Fixed bug (first format entry couldn't be * * selected.) * * 5.9.93 R.Bödi Now TeXFormat is a MUI application. * * 14.9.93 R.Bödi Added 'Save' button. * * * *************************************************************************** * * * Copyright © 1992-1993 Richard Bödi, All rights reserved. * * * ***************************************************************************/ /*----------------------------- INCLUDES ----------------------------------*/ #include "string.h" #include "stdio.h" #include "stdlib.h" #include "dos.h" #include "workbench/workbench.h" #include "workbench/startup.h" #include "libraries/mui.h" #include "clib/alib_protos.h" #include "clib/intuition_protos.h" #include "clib/exec_protos.h" #include "clib/dos_protos.h" #include "clib/graphics_protos.h" #include "clib/gadtools_protos.h" #include "clib/icon_protos.h" #include "clib/wb_protos.h" #include "clib/muimaster_protos.h" #include "pragmas/intuition_pragmas.h" #include "pragmas/exec_pragmas.h" #include "pragmas/dos_pragmas.h" #include "pragmas/graphics_pragmas.h" #include "pragmas/gadtools_pragmas.h" #include "pragmas/icon_pragmas.h" #include "pragmas/wb_pragmas.h" #include "pragmas/muimaster_pragmas.h" /*--------------------------- DEFINES -------------------------------------*/ #define VERSION " V2.00 " #define COMMENTLENGTH 82 #define CMDSTRLENGTH 512 #define ID_FORMAT_SEL 1 #define ID_SAVE 2 #define ID_ABOUT 1000 #define ID_HIDE 10000 #define ID_SHOW 10001 #define NEWLINE "\n" /*-------------------- STRUCTURE DEFINITIONS ------------------------------*/ enum ScanError { SCAN_OK, NO_LOCK, NO_FORMAT, NO_ENV, NO_MATCH, NO_MEMORY }; enum ErrorIDs { ERR_NOERROR, ERR_FORMATFILES = 10, ERR_MUI = 20, ERR_NOMUILIB = 30 }; enum Keywords { KW_CURRENTFORMAT, KW_FORMATPATH, KW_PATTERN, LAST_KW }; struct FormatNode { struct FormatNode *NextNode; char Name[FNSIZE]; char Comment[COMMENTLENGTH]; int ID; }; struct TeXFormat { struct FormatNode *FirstNode; char **FormatArray; struct FormatNode *CurrentFormat; int MaxCommentLength; int MaxCommentLines; char DummyComment[COMMENTLENGTH]; int NoOfFormats; }; struct Settings { long ArgPtr[LAST_KW]; char ArgStr[LAST_KW][FMSIZE]; // FMSIZE see file dos.h char CurrentFormat[FNSIZE]; }; /*--------------------- FUNCTION PROTOTYPES -------------------------------*/ BOOL OpenLibs (void); void ParseShell (int, char **, struct Settings *); void ParseWB (struct WBStartup *, struct Settings *); enum ScanError ScanFormatPath (struct TeXFormat *, struct Settings *); void HandleIDCMP (struct TeXFormat *, struct Settings *); int LineLength (char *); int NoOfLines (char *); char *ConvertNL (char *); void Cleanup (char *, enum ErrorIDs); /*------------------------ EXTERNAL VARIABLES ----------------------------*/ extern struct Library *SysBase; extern struct DOSBase *DOSBase; extern struct GfxBase *GfxBase; extern struct IntuitionBase *IntuitionBase; extern struct GadToolsBase *GadToolsBase; extern struct IconBase *IconBase; extern struct WorkbenchBase *WorkbenchBase; /*-------------------------- GLOBAL DATA ----------------------------------*/ struct Library *MUIMasterBase; char Version[] = "$VER: TeXFormat Release " VERSION " (" __DATE__ ") © R.Bödi"; char Title[] = "TeXFormat " VERSION " © R.Bödi"; char Author[] = "Richard Bödi\nKäsenbachstr. 10/2\n72076 Tübingen\nGermany\n\ne-mail: mmisa01@mailserv.zdv.uni-tuebingen.de"; char *Keywords[] = { "CURRENTFORMAT", "FORMATPATH", "PATTERN" }; char *Switchs[] = { "/K", "/K", "/K" }; STRPTR ErrorMsg[] = { "", "Couldn't find directory", "Couldn't find a TeX format file in ", "Environment variable unset", "Couldn't find TeX format file defined by the environment variable ", "Not enough memory available" }; struct NewMenu Menu[] = { NM_TITLE, "File", NULL, 0, 0, NULL, NM_ITEM, "About", NULL, 0, 0, (APTR)ID_ABOUT, NM_ITEM, NM_BARLABEL, NULL, 0, 0, NULL, NM_ITEM, "Quit", "Q", 0, 0, (APTR)MUIV_Application_ReturnID_Quit, NM_END }; /*--------------------------- MUI Objects ---------------------------------*/ Object *App; Object *Win; Object *Select_Gad; Object *Save_Gad; Object *Done_Gad; Object *Description_TextField; /*------------------------------- CODE ------------------------------------*/ main (int argc, char *argv[]) { struct TeXFormat TeXFormat; struct Settings Settings; enum ScanError FormatAvail; char ErrorStrg[FMSIZE]; if (argc == 0) ParseWB ((struct WBStartup *)argv, &Settings); if (argc > 1) ParseShell (argc, argv, &Settings); if (OpenLibs ()) { FormatAvail = ScanFormatPath (&TeXFormat, &Settings); if (FormatAvail == SCAN_OK) { App = ApplicationObject, MUIA_Application_Title , "TeXFormat", MUIA_Application_Version , Version, MUIA_Application_Copyright , "© 1992-93, Richard Bödi", MUIA_Application_Author , Author, MUIA_Application_Description, "Select TeX format files easily.", MUIA_Application_Base , "TEXFORMAT", MUIA_Application_Menu , Menu, SubWindow, Win = WindowObject, MUIA_Window_ID, 0, MUIA_Window_Title, Title, WindowContents, VGroup, Child, HGroup, Child, Select_Gad = Radio ("TeX format", TeXFormat.FormatArray), End, Child, HGroup, GroupFrameT ("Description"), Child, Description_TextField = TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, TeXFormat.DummyComment, End, End, Child, VSpace(0), Child, HGroup, Child, Save_Gad = KeyButton ("Save", 's'), Child, HSpace(0), Child, HSpace(0), Child, Done_Gad = KeyButton ("Done", 'd'), End, End, End, End; if (App) { DoMethod (Win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); DoMethod (App, MUIM_Notify, MUIA_Application_Iconified, FALSE, App, 2, MUIM_Application_ReturnID, ID_SHOW); DoMethod (App, MUIM_Notify, MUIA_Application_Iconified, TRUE, App, 2, MUIM_Application_ReturnID, ID_HIDE); DoMethod (Select_Gad, MUIM_Notify, MUIA_Radio_Active, MUIV_EveryTime, App, 2, MUIM_Application_ReturnID, ID_FORMAT_SEL); DoMethod (Save_Gad, MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, ID_SAVE); DoMethod (Done_Gad, MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); DoMethod (Win, MUIM_Window_SetCycleChain, Select_Gad, Save_Gad, Done_Gad, NULL); set (Win, MUIA_Window_Open, TRUE); set (Select_Gad, MUIA_Radio_Active, TeXFormat.CurrentFormat->ID); HandleIDCMP (&TeXFormat, &Settings); Cleanup (NULL, ERR_NOERROR); } else Cleanup ("Couldn't create MUI application.", ERR_MUI); } else { sprintf (ErrorStrg, "%s%s\n", ErrorMsg[FormatAvail], Settings.ArgStr[KW_FORMATPATH]); Cleanup (ErrorStrg, ERR_FORMATFILES); } } else { sprintf (ErrorStrg, "No muimaster.library of version >= %d\n", MUIMASTER_VMIN); Cleanup (ErrorStrg, ERR_NOMUILIB); } } /*************************************************************************** * * * Function name : ParseWB * * * * Description : Fetches and parses the ToolTypes from the TeXFormat icon.* * Allowed tooltypes are : * * CURRENTFORMAT (Specifies the name of the environment * * variable in which the name of the * * current TeX format file is stored.) * * FORMATPATH (Specifies the path for the TeX * * format files is stored.) * * PATTERN (Specifies the file pattern for fromat files. * * Typically it's #?.fmt.) * * * *************************************************************************** * * * Synopsis : ParseWB (WBArgStr, Settings) * * * * Parameters : * * (struct WBStartup **) WBArgStr: * * The WB argument string. * * (struct Settings *) Settings: * * The tags of theses structure are filled by this procedure. * * * * Return value : None * * * ***************************************************************************/ void ParseWB (struct WBStartup *WBArgStr, struct Settings *Settings) { struct DiskObject *DiskObj; struct WBArg *WBArg; char **ToolArray; WBArg = WBArgStr->sm_ArgList; if (WBArg->wa_Name) // get tooltypes if (DiskObj = GetDiskObject (WBArg->wa_Name)) { ToolArray = (char **)DiskObj->do_ToolTypes; stpcpy (Settings->ArgStr[KW_CURRENTFORMAT], FindToolType (ToolArray, Keywords[KW_CURRENTFORMAT])); stpcpy (Settings->ArgStr[KW_FORMATPATH], FindToolType (ToolArray, Keywords[KW_FORMATPATH])); stpcpy (Settings->ArgStr[KW_PATTERN], FindToolType (ToolArray, Keywords[KW_PATTERN])); FreeDiskObject (DiskObj); } GetVar (Settings->ArgStr[KW_CURRENTFORMAT], Settings->CurrentFormat, sizeof (Settings->CurrentFormat), GVF_GLOBAL_ONLY); } /*************************************************************************** * * * Function name : ParseShell * * * * Description : Parses the commandline for parameters. * * Allowed parameters are : * * CURRENTFORMAT/K (Specifies the name of the environment* * variable in which the name of the * * current TeX format file is stored. * * FORMATPATH/K (Specifies the the path for the TeX * * format files is stored. * * PATTERN(K (Specifies the file pattern for fromat files* * Typically it's #?.fmt.) * * * *************************************************************************** * * * Synopsis : ParseShell (NoOfArgs, Arg, Settings) * * * * Parameters : * * (int) NoOfArgs: * * The number of arguments. * * (char **) Arg: * * The shell argument string. * * (struct Settings *) Settings: * * The tags of theses structure are filled by this procedure. * * * * Return value : None * * * ***************************************************************************/ void ParseShell (int NoOfArgs, char **Arg, struct Settings *Settings) { int kword; struct RDArgs *RDArgs; char Template[CMDSTRLENGTH]; for (kword = 0, Template[0] = 0; kword < LAST_KW; kword++) { if (Template[0]) strcat (Template, ","); strcat (Template, Keywords[kword]); strcat (Template, Switchs[kword]); } if (RDArgs = ReadArgs (Template, Settings->ArgPtr, NULL)) { for (kword = 0; kword < LAST_KW; kword++) if (Settings->ArgPtr[kword]) stpcpy (Settings->ArgStr[kword], (char *)Settings->ArgPtr[kword]); } else PrintFault (IoErr (), "Error reading arguments"); GetVar (Settings->ArgStr[KW_CURRENTFORMAT], Settings->CurrentFormat, sizeof (Settings->CurrentFormat), GVF_GLOBAL_ONLY); FreeArgs (RDArgs); } /*************************************************************************** * * * Function name : ScanFormatPath * * * * Description : Scans the format path for TeX format files, creates * * and fills for each file a struct FormatNode, updates * * the TeXFormat structure and reads the Settings->Texformat* * environment variable. * * * *************************************************************************** * * * Synopsis : ScanFormatPath (TeXFormat, Settings) * * * * Parameters : * * (struct TeXFormat *) TeXFormat: * * This structure will be filled with the names of the format * * files found. * * (struct Settings *) Settings: * * Contains the path and extension of the format files and the * * name of the TEXFORMAT enviroenment variable. * * * * Return value : (enum ScanError) * * SCAN_OK, if at least one TeX format file was found and the content * * this variable matches a scanned TeX format file. * * NO_LOCK, if path couldn't be locked for examination. * * NO_FORMAT, if no TeX format file was found. * * NO_ENV, if one of the environment variables is unset. * * NO_MATCH, if content of the CURRENTFORMAT environment variable * * matches no scanned format file. * * NO_MEMORY, if no memory for the FormatNodes was available. * * * ***************************************************************************/ enum ScanError ScanFormatPath (struct TeXFormat *TeXFormat, struct Settings *Settings) { int Index; BPTR OldLock, NewLock; BOOL ActFormatFound = FALSE, Match, Error = FALSE; struct AnchorPath APath; struct FormatNode *NewNode, *LastNode = NULL; char FormatName[FNSIZE]; APath.ap_BreakBits = 0; APath.ap_Strlen = 0; TeXFormat->FirstNode = NULL; TeXFormat->MaxCommentLength = 1; TeXFormat->MaxCommentLines = 1; if ((strlen (Settings->CurrentFormat) != 0) && (strlen (Settings->ArgStr[KW_FORMATPATH]) != 0)) { if (NewLock = Lock (Settings->ArgStr[KW_FORMATPATH], ACCESS_READ)) { OldLock = CurrentDir (NewLock); for (Index = 0, Match = MatchFirst (Settings->ArgStr[KW_PATTERN], &APath); !Match; Match = MatchNext (&APath), Index++) { SplitName (APath.ap_Info.fib_FileName, '.', FormatName, 0, sizeof (FormatName)); if (strlen (FormatName) == 0) Index--; else { if (NewNode = (struct FormatNode *) calloc (sizeof (struct FormatNode), 1)) { if (TeXFormat->FirstNode == NULL) TeXFormat->FirstNode = NewNode; else LastNode->NextNode = NewNode; sprintf (NewNode->Name, "%-s", FormatName); stpcpy (NewNode->Comment, APath.ap_Info.fib_Comment); LastNode = NewNode; if (!strcmpi (Settings->CurrentFormat, FormatName)) { TeXFormat->CurrentFormat = NewNode; ActFormatFound = TRUE; } if (LineLength (NewNode->Comment) > TeXFormat->MaxCommentLength) TeXFormat->MaxCommentLength = LineLength (NewNode->Comment); if (NoOfLines (NewNode->Comment) > TeXFormat->MaxCommentLines) TeXFormat->MaxCommentLines = NoOfLines (NewNode->Comment); if (NoOfLines (NewNode->Comment) > 1) ConvertNL (NewNode->Comment); } else { Error = TRUE; break; } } } MatchEnd (&APath); CurrentDir (OldLock); UnLock (NewLock); TeXFormat->NoOfFormats = Index; if (Error) return (NO_MEMORY); if (!TeXFormat->NoOfFormats) return (NO_FORMAT); if (!ActFormatFound) return (NO_MATCH); TeXFormat->FormatArray = (char **)calloc (TeXFormat->NoOfFormats + 1, sizeof (TeXFormat->FormatArray[0])); for (Index = 0, TeXFormat->DummyComment[0] = 0; Index < TeXFormat->MaxCommentLength; Index++) strcat (TeXFormat->DummyComment, " "); for (Index = 1; Index < TeXFormat->MaxCommentLines; Index++) strcat (TeXFormat->DummyComment, NEWLINE); if (TeXFormat->FormatArray) { for (Index = 0, NewNode = TeXFormat->FirstNode; Index < TeXFormat->NoOfFormats; Index++, NewNode = NewNode->NextNode) TeXFormat->FormatArray[Index] = NewNode->Name; strsrt (TeXFormat->FormatArray, TeXFormat->NoOfFormats); TeXFormat->FormatArray[TeXFormat->NoOfFormats] = NULL; for (NewNode = TeXFormat->FirstNode; NewNode != NULL; NewNode = NewNode->NextNode) for (Index = 0; Index < TeXFormat->NoOfFormats; Index++) if (TeXFormat->FormatArray[Index] == NewNode->Name) NewNode->ID = Index; } else return (NO_MEMORY); } else return (NO_LOCK); } else return (NO_ENV); return (SCAN_OK); } /*************************************************************************** * * * Function name : HandleIDCMP * * * * Description : Tests IDCMP port for incoming messages. * * This function returns if the window close gaget or the * * DONE gadget was activated. * * * *************************************************************************** * * * Synopsis : HandleIDCMP (TeXFormat, Settings) * * * * Parameters : * * (struct TeXFormat *) TeXFormat: * * This structure contains the names of the TeX formats available.* * (struct Settings *) Settings: * * Contains the path and extension of the format files and the * * name of the TEXFORMAT enviroenment variable. * * * * Return value : None * * * ***************************************************************************/ void HandleIDCMP (struct TeXFormat *TeXFormat, struct Settings *Settings) { BOOL Running = TRUE; ULONG Signal; struct FormatNode *FNode; int FormatID; char CMDStrg[128]; while (Running) { switch (DoMethod (App, MUIM_Application_Input, &Signal)) { case MUIV_Application_ReturnID_Quit: Running = FALSE; break; case ID_HIDE: set (Description_TextField, MUIA_Text_Contents, TeXFormat->DummyComment); break; case ID_SHOW: set (Description_TextField, MUIA_Text_Contents, TeXFormat->CurrentFormat->Comment); break; case ID_FORMAT_SEL: get (Select_Gad, MUIA_Radio_Active, &FormatID); for (FNode = TeXFormat->FirstNode; FNode != NULL; FNode = FNode->NextNode) if (FNode->ID == FormatID) break; TeXFormat->CurrentFormat = FNode; set (Description_TextField, MUIA_Text_Contents, FNode->Comment); SetVar (Settings->ArgStr[KW_CURRENTFORMAT], FNode->Name, strlen (FNode->Name), GVF_GLOBAL_ONLY); break; case ID_SAVE: sprintf (CMDStrg, "copy env:%s envarc:%s", Settings->ArgStr[KW_CURRENTFORMAT], Settings->ArgStr[KW_CURRENTFORMAT]); system (CMDStrg); break; case ID_ABOUT: MUI_Request (App, Win, 0, NULL, "OK", "\n TeXFormat %s \n\n A Format File Selector for TeX \n\n (c) 1993 by Richard Bödi\n\n Mathematisches Institut\n Universität Tübingen\n Auf der Morgenstelle 10\n 72076 Tübingen\n Germany\n\ne-mail :\n mmisa01@mailserv.zdv.uni-tuebingen.de\n"); break; } if (Running && Signal) Wait (Signal); } } /*************************************************************************** * * * Function name : LineLength * * * * Description : Determines the length of the longest lines of a string * * which contains '\n' as a newline token. * * * *************************************************************************** * * * Synopsis : LineLength (Strg) * * * * Parameters : * * (char *) Strg: * * The input string. * * * * Return value : * * (int) The length of the longest line. * * * ***************************************************************************/ int LineLength (char *Strg) { char Buffer[COMMENTLENGTH]; char *String = Strg; int MaxLength = 0; while (1) { String = stptok (String, Buffer, sizeof (Buffer), "\\"); if (strlen (Buffer) > MaxLength) MaxLength = strlen (Buffer); if (String[0] == '\0') break; if (String[1] == 'n') String++; String++; } return (MaxLength); } /*************************************************************************** * * * Function name : NoOfLines * * * * Description : Determines the number of lines of a string * * which contains '\n' as a newline token. * * * *************************************************************************** * * * Synopsis : NoOfLines (Strg) * * * * Parameters : * * (char *) Strg: * * The input string. * * * * Return value : * * (int) The number of lines in the string. * * * ***************************************************************************/ int NoOfLines (char *Strg) { char Buffer[COMMENTLENGTH]; char *String = Strg; int Lines = 1; while (1) { String = stptok (String, Buffer, sizeof (Buffer), "\\"); if (String[0] == '\0') break; if (String[1] == 'n') { String++; Lines++; } String++; } return (Lines); } /*************************************************************************** * * * Function name : ConvertNL * * * * Description : Converts \n to newline characters. * * * *************************************************************************** * * * Synopsis : ConvertNL (Strg) * * * * Parameters : * * (char *) Strg: * * The input string. * * * * Return value : * * (char *) Same as the input string. * * * ***************************************************************************/ char *ConvertNL (char *Strg) { char Buffer[COMMENTLENGTH]; char *String = Strg; while (1) { String = stptok (String, Buffer, sizeof (Buffer), "\\"); if (String[0] == '\0') break; if (String[1] == 'n') { String[0] = ' '; String[1] = '\n'; String++; } String++; } return (Strg); } /*************************************************************************** * * * Function name : OpenLibs * * * * Description : Opens the following libraries: * * mui.library * * * *************************************************************************** * * * Synopsis : OpenLibs () * * * * Parameters : None * * * * Return value : BOOL * * TRUE, if successful * * FALSE, if not. * * * ***************************************************************************/ BOOL OpenLibs () { if (MUIMasterBase = (struct Library *)OpenLibrary (MUIMASTER_NAME, MUIMASTER_VMIN)) return (TRUE); else return (FALSE); } /*************************************************************************** * * * Function name : Cleanup * * * * Description : Frees all allocated memory, closes down the MUI * * application, possibly prints some error message and * * exits. * * * *************************************************************************** * * * Synopsis : Cleanup (Strg, ErrorID) * * * * Parameters : * * (char *) Strg: * * Pointer to a message string. * * (enum ErrorIDs) ErrorID: * * Error code identifier. * * * * Return value : None * * * ***************************************************************************/ void Cleanup (char *Strg, enum ErrorIDs ErrorID) { if (Strg) puts (Strg); if (App) MUI_DisposeObject (App); if (MUIMasterBase) CloseLibrary (MUIMasterBase); exit (ErrorID); }